home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-19 | 9.2 KB | 361 lines | [TEXT/CWIE] |
- #include "Exceptions.h"
- #include "DatabaseDocument.h"
- #include "DBRecord.h"
- #include "DBElement.h"
- #include "DBProperty.h"
- #include "DataRecord.h"
- #include "ReferenceTemplates.h"
-
- #include "Application.h"
- #include "ScriptableDBDocument.h"
- #include "HFSBackingStore.h"
-
- //
- // For MarkTokenMergeProc
- //
- #include "MarkToken.h"
-
- #include "MoreAEM.h"
- #include "ResolveObjectSpecifier.h"
- #include "Accessor.h"
- #include "CoreSuite.h"
- #include "TransactionSuite.h"
- #include "PseudoRandom.h"
-
- #include <Events.h>
- #include <Gestalt.h>
-
-
- #include "Futures.h"
- #include "ThreadContext.h"
- #include <Threads.h>
-
- //
- // Initialization stuff
- //
- #include "Fonts.h"
- #include "Windows.h"
- #include "Menus.h"
- #include "TextEdit.h"
- #include "Dialogs.h"
-
-
- #include "EventHandlerTable.h"
-
- class TApplication;
-
- void MainLoop(TEventHandlerTable& eventTable);
- void InitAll();
-
- TTokenDescriptor MakeNullContainer();
-
- Boolean gApplicationRunning = false;
-
- pascal OSErr QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon);
-
-
- Boolean gHasAppleEvents;
-
-
- void InstallStringCompareBehavior();
-
-
- //--------------------------------------------------------------------------------
- // main
- //--------------------------------------------------------------------------------
- main()
- {
- TEventHandlerTable eventTable;
- OSErr err = noErr;
-
- //
- // Make the universe come alive
- //
- InitAll();
-
- //
- // Before any threads are created, make sure that the main thread
- // gets swap in and swap out context switch messages
- //
- ThreadCreateNotifyHandler(kApplicationThreadID, 0);
-
- //
- // Use a different set of random numbers
- // every time
- //
- SetRandomSeed(TickCount());
-
- #if 1
- Try
- {
- // DebugStr("\pset up try");
-
- FailErr(-42);
-
- DebugStr("\pcame back after throw?");
- }
- Catch(err)
- {
- //if(err == -42)
- // DebugStr("\pcaught the exception");
- //else
- // DebugStr("\pwrong value?");
- }
-
- // DebugStr("\pcontinue with life");
- #endif
-
- Try
- {
- //
- // Insure that gApplication is initialized
- //
- TApplication::Instance();
-
- TDescriptor::SetCallbackFlags(kAEIDoWhose | kAEIDoMarking);
- InstallStringCompareBehavior();
- InstallNullContainerCreationProc(MakeNullContainer);
- InstallPreResolveProc(ResolveObjectSpecifier);
- InstallMergeTokensProc(MarkTokenMergeProc);
- TAccessor::InstallAEHandlers();
-
- //
- // Install our event handlers into our main event-handler table
- //
- eventTable.InstallHandler(kCoreEventClass, kAEQuitApplication, (EventHandlerProcPtr) &QuitApplicationEvent, 0);
- TCoreSuite::InstallAEHandlers(eventTable);
- TTransactionSuite::InstallAEHandlers(eventTable);
-
- //
- // MainLoop will not return until gApplicationRunning goes false
- //
- gApplicationRunning = true;
- MainLoop(eventTable);
- }
- Catch(err)
- {
- if(err != userCanceledErr)
- DebugStr("\pCaught an error in testmain");
- }
-
- //
- // Before we bail out, we should save all of our documents
- //
- TApplication::Instance()->TearDownApplication();
-
- return 0;
- }
-
- #define kDBSleep (60*60)
-
- //----------------------------------------------------------------------------------------
- // MainLoop:
- //----------------------------------------------------------------------------------------
- void MainLoop(TEventHandlerTable& eventTable)
- {
- OSErr err = noErr;
-
- while(gApplicationRunning == true)
- {
- Try
- {
- unsigned long lastWNECallTick = 0;
-
- //
- // Active threads includes the main thread. If there
- // are no active threads, then call WNE all the time.
- // If there are active threads, let them run for
- // at least 10 ticks before calling WNE.
- //
- // If we had a real scheduler, then the scheduler should
- // ask the threads how busy they are; if there's a lot
- // of work to be done, then the throttle should be high
- // (10 or 20 ticks). If there are threads running but they
- // aren't doing anything too important, then the throttle
- // could be much lower. (The throttle could just be the
- // max of what any thread said it wanted.)
- //
- Boolean threadsActive = TThreadContext::ActiveThreads() > 1;
- unsigned long throttleWNETicks = threadsActive ? 10 : 0;
-
- if((TickCount() - lastWNECallTick) > throttleWNETicks)
- {
- //
- // Similarly, if there are threads active, we don't want
- // to sleep for any longer than necessary (don't use zero,
- // because that value is special); note that it's unlikely
- // that WNE will actually come back in one tick.
- //
- // If there are no active threads, then sleep for a "long"
- // time.
- //
- // Again, if we had a scheduler it should ask each thread
- // how long it thought the sleep time should be, and take
- // the minimum returned by any thread. For the most part,
- // threads that want a high throttle also want a low sleep
- // time. However, an idle (or mostly inactive) thread might
- // want a low throttle for the time being, but might also
- // desire a low sleep time because it needs to do periodic
- // tasks every N ticks, or it's about to wake up, or...
- //
- long sleepTimeForWNE = threadsActive ? 1 : kDBSleep;
-
- //
- // Remember the tickcount that we called WaitNextEvent
- // at _after_ WNE returns (since we never know how long
- // our clients will hog the CPU for)
- //
- eventTable.Receive(kAEReceiveOneEvent, sleepTimeForWNE);
- lastWNECallTick = TickCount();
- }
-
- //
- // Idle our application and allow other threads to run.
- //
- YieldToAnyThread();
- TApplication::Instance()->Idle();
- }
- Catch(err)
- {
- //
- // For now, only pass along user canceled errors
- // (n.b. Errors are not thrown through AEProcessAppleEvent,
- // so it is unlikely that we will ever get here)
- //
- if(err == userCanceledErr)
- {
- gApplicationRunning = false;
- Throw(err);
- }
-
- DebugStr("\pOh no, an uncaught main-loop failure!");
- }
- }
- } // MainLoop
-
- //----------------------------------------------------------------------------------------
- // QuitApplicationEvent:
- //----------------------------------------------------------------------------------------
- pascal OSErr QuitApplicationEvent(TAEvent& /*ae*/, TAEvent& /*reply*/, long /*refCon*/)
- {
- //
- // You should never call ExitToShell from an AppleEvent handler
- //
- gApplicationRunning = false;
-
- return noErr;
- } // QuitApplicationEvent
-
-
- //----------------------------------------------------------------------------------------
- // InitAll
- //
- // Initialize all of the relivant Macintosh managers. We probably
- // don't need to do _all_ of this for db+.
- //----------------------------------------------------------------------------------------
- void InitAll()
- {
- long heapSpace;
- Ptr appLimit;
- THz appBase;
- short callsToMoreMasters = 10;
-
- appBase = ApplicZone();
- appLimit = GetApplLimit();
- heapSpace = FreeMem();
- MaxApplZone();
- appLimit = GetApplLimit();
- heapSpace = FreeMem();
- while( callsToMoreMasters-- )
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0);
-
- //
- // Initialize the Object Support Library
- // and install the futures package.
- //
- AEObjectInit();
- InitFutures(ThreadCreateHandler);
-
- #if 0
- long gestaltResult;
- //
- // Get the SysEnvirons record
- //
- SysEnvirons( 1, &gThisMacintosh );
-
- //
- // Check to see if AppleEvents are available (we are going to REQUIRE them)
- //
- OSErr theErr = Gestalt( gestaltAppleEventsAttr, &gestaltResult );
- gHasAppleEvents = ( (theErr == noErr) && ((gestaltResult & (1L << gestaltAppleEventsPresent)) != 0) );
- #endif
- } // InitAll
-
-
- //----------------------------------------------------------------------------------------
- // MakeNullContainer:
- //----------------------------------------------------------------------------------------
- TTokenDescriptor MakeNullContainer()
- {
- TTokenDescriptor nullContainerDesc;
-
- nullContainerDesc.AdoptToken(TApplication::Instance());
-
- return nullContainerDesc;
- } // MakeNullContainer
-
- #if 0
-
- //----------------------------------------------------------------------------------------
- // Global operator new
- //----------------------------------------------------------------------------------------
- void* operator new(size_t size)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // Global operator delete
- //----------------------------------------------------------------------------------------
- void operator delete(void* object, size_t size)
- {
-
- }
-
- #endif
-
- // From UException.cp:
- //
- // The C++ draft standard states that the Exception Handling mechanism
- // call terminate() when encountering certain unrecoverable errors,
- // such as:
- // - Not finding a handler for a thrown exception
- // - Finding a corrupted stack
- // - A destructor called during stack unwinding tries to exit
- // using an exception
- //
- // The default implementation of terminate() calls abort().
- //
- // abort() is a standard ANSI C library function. Since PowerPlant
- // programs frequently don't include the ANSI C library, the abort()
- // function is defined below.
- //
- // Do NOT include this file in your project if you use the ANSI C library.
- // If you use the ANSI C Library, include the file console.stubs.c (in the
- // folder with the SIOUX libraries) in your project instead of UException.cp.
-
- extern "C" void abort(void);
- void abort(void)
- {
- DebugStr("\pAborting Program due to uncaught exception. Try recompiling TestMain.cp and run again (MW bug?)");
-
- ::ExitToShell();
- }
-